# coding=utf-8
import hashlib
import json
import logging
import random
import string
import urllib2
from decimal import Decimal

import time
import xmltodict
from django.db import transaction
from wechatpy.pay import dict_to_xml

from worldcup.apps.userModel.models import UserUnion, PayDeal, OrderHead, OrderDetail
from worldcup.commons.CommonResult import rest, CommonResult
from worldcup.commons.IdGenerator import generateId
from worldcup.commons.WXBizDataCrypt import WXBizDataCrypt
from worldcup.rest_views.shopcart_rest_view import add_shopcart

mini_appid = "wxd93aedeb5302d03b"
mini_secret = "3e72a1c9d4b306f1de3f2dd079c04054"


logger = logging.getLogger('django')

@rest
def mini_program_login(request):
	code = request.GET.get("code")
	access_token_url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + mini_appid + "&secret=" + mini_secret + \
					   "&js_code=" + code + "&grant_type=authorization_code"
	response = urllib2.urlopen(access_token_url)
	response_json = response.read()
	parsed_content = json.loads(response_json)
	if parsed_content.get('errcode') is not None:
		logger.error("小程序code凭证校验失败")
		return CommonResult(-1, "小程序code凭证校验失败")

	logger.info(parsed_content)
	mini_openid = parsed_content["openid"]
	session_key = parsed_content["session_key"]
	try:
		unionid = parsed_content["unionid"]
	except KeyError:
		return CommonResult(-1, session_key)

	user_unions = UserUnion.objects.filter(unionid=unionid).all()
	if len(user_unions) > 0:
		# update
		user_union = user_unions[0]
		user_union.mini_openid = mini_openid
		user_union.save()
	else:
		user_union = UserUnion(unionid=unionid, mini_openid=mini_openid)
		user_union.save()
	return CommonResult(0, session_key)


@rest
def mini_program_userinfo(request):
	encryptedData = request.GET.get("userInfo")
	session_key = request.GET.get("sessionKey")
	iv = request.GET.get("iv")
	logger.info("userInfo = " + encryptedData)
	pc = WXBizDataCrypt(mini_appid, session_key)
	user_info = pc.decrypt(encryptedData, iv)
	mini_openid = user_info["openId"]
	union_id = user_info["unionId"]
	user_unions = UserUnion.objects.filter(unionid=union_id).all()
	if len(user_unions) > 0:
		# update
		user_union = user_unions[0]
		user_union.mini_openid = mini_openid
		user_union.save()
	else:
		user_union = UserUnion(unionid=union_id, mini_openid=mini_openid)
		user_union.save()
	return CommonResult(0, "success")


def sign_param(prepay_id, isMiniProgram):
	dict_param = {}
	dict_param["appId"] = "wxd93aedeb5302d03b" if isMiniProgram else "wx3d857b42797b5eb4"
	dict_param["timeStamp"] = int(time.time())
	dict_param["nonceStr"] = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
	dict_param["package"] = "prepay_id=" + prepay_id
	dict_param["signType"] = "MD5"
	params = '&'.join(['%s=%s' % (key, dict_param[key]) for key in sorted(dict_param)])
	params = params + "&key=xz2X31GP1zfoSfOWq4gPqwDdaD6Ggl3Q"
	dict_param["signature"] = hashlib.md5(params).hexdigest().upper()
	return dict_param


@rest
def mini_program_pay(request):
	try:
		reqest_params = json.loads(request.body)
	except ValueError:
		return CommonResult(-1, "数据格式错误")
	total_fee = reqest_params["totalFee"]
	if total_fee == "" or total_fee is None:
		return CommonResult(-1, "totalFee不能为空")
	# 金额转换为分
	total_fee = str((Decimal(100) * Decimal(total_fee)).quantize(Decimal('0')))
	user_id = reqest_params["openid"]
	if user_id == "" or user_id is None:
		return CommonResult(-1, "user_id不能为空")
	out_trade_no = reqest_params.get("orderCode")
	# if out_trade_no is None:
	# 	out_trade_no = generateId()
	if out_trade_no is None:
		return CommonResult(-1, "orderCode不能为空")

	# 校验金额与订单是否相等
	order_head = OrderHead.objects.values("total_amount").filter(order_code=out_trade_no).get()
	if str(int(order_head["total_amount"]) * 100) != total_fee:
		logger.error("orderAmount = " + str(order_head["total_amount"] * 100) + " , totalFee = " + str(total_fee))
		return CommonResult(-1, "订单金额与支付金额不相等")

	isMiniProgram = reqest_params.get("isMiniProgram")
	if isMiniProgram is None:
		isMiniProgram = True
	mini_openid = UserUnion.objects.filter(openid=user_id).get().mini_openid
	data = {
		"appid": "wxd93aedeb5302d03b" if isMiniProgram else "wx3d857b42797b5eb4",
		"mch_id": "1446925902",
		"body": "worldcup",
		"out_trade_no": out_trade_no,
		"total_fee": total_fee,
		"notify_url": "https://worldcup.dmpb.com.cn/api/pay/notify",
		"trade_type": "JSAPI",
		"openid": mini_openid if isMiniProgram else user_id,
		"nonce_str": ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15)),
	}

	params = '&'.join(['%s=%s' % (key, data[key]) for key in sorted(data)])
	params = params + "&key=xz2X31GP1zfoSfOWq4gPqwDdaD6Ggl3Q"
	data["sign"] = hashlib.md5(params).hexdigest().upper()
	xml_request = xmltodict.unparse({"xml": data})
	request = urllib2.Request("https://api.mch.weixin.qq.com/pay/unifiedorder", data=xml_request)
	response = urllib2.urlopen(request)
	response_dict = xmltodict.parse(response)['xml']
	logger.info(response_dict)

	if response_dict.get("return_code") != "SUCCESS":
		logger.error("支付统一支付失败, " + response_dict.get("return_msg"))
		return CommonResult(-1, response_dict.get("return_msg"))
	if response_dict["result_code"] != "SUCCESS":
		logger.error("支付回调失败," + response_dict["err_code_des"])
		return CommonResult(-1, response_dict.get("err_code_des"))
	prepay_id = response_dict["prepay_id"]
	# 记录下单流水
	trade_id = generateId()
	paydeal = PayDeal(trade_id=trade_id, openid=user_id, prepay_id=prepay_id, order_id=out_trade_no,
					  type=1 if isMiniProgram else 2,
					  request_amount=total_fee, pay_status=1, operate_status=1, created_at=int(time.time()),
					  updated_at=int(time.time()))
	paydeal.save()
	# sign
	result = sign_param(prepay_id, isMiniProgram)
	# 等于号传到小程序不能解析，小程序自己拼package  prepay_id=....
	result["package"] = prepay_id
	result["orderCode"] = out_trade_no
	result["openid"] = user_id
	return CommonResult(0, result)


@transaction.atomic
@rest
def mini_program_pay_failed(request):
	try:
		reqest_params = json.loads(request.body)
	except ValueError:
		return CommonResult(-1, "数据格式错误")
	openid = reqest_params.get("openid")
	logger.info("openeid " + openid)
	order_code = reqest_params.get("orderCode")
	err_msg = reqest_params.get("errMsg")

	logger.info("orderCode = " + order_code)
	if "cancel" in err_msg:
		# 取消
		status = 5
	else:
		# 失败
		status = 4
	timestamp = int(time.time())
	# pay_deal处理
	pay_deals = PayDeal.objects.filter(order_id=order_code).all()
	if len(pay_deals) > 0:
		pay_deal = pay_deals[0]
		pay_deal.pay_status = status
		pay_deal.error_message = err_msg
		pay_deal.updated_at = timestamp
		pay_deal.save()

	# 订单处理
	order_head = OrderHead.objects.filter(order_code=order_code).get()
	order_head.order_status = 40
	order_head.pay_status = 30 if status == 5 else 40
	order_head.updated_at = timestamp
	order_head.save()

	# 订单商品加回购物车
	order_details = OrderDetail.objects.values("sku_code", "qty").filter(order_code=order_code).all()
	for order_detail in order_details:
		add_shopcart(openid, order_detail["sku_code"], order_detail["qty"])

	return CommonResult(0, "success")




